package com.xinqi.modules.exam.analyze.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.ImmutableList;
import com.xinqi.common.base.dto.QuestionBaseDTO;
import com.xinqi.common.base.dto.QuestionOptionsDTO;
import com.xinqi.common.base.dto.utils.QuestionUtils;
import com.xinqi.common.base.enums.QuestionTypeEnum;
import com.xinqi.common.base.enums.YesNoEnum;
import com.xinqi.common.base.error.CommonErrors;
import com.xinqi.common.base.response.PageInfo;
import com.xinqi.common.base.response.Param;
import com.xinqi.common.base.utils.number.BigDecimals;
import com.xinqi.common.mybatis.utils.Pages;
import com.xinqi.common.mybatis.utils.Queries;
import com.xinqi.modules.exam.analyze.convert.CourseExamPaperAnalyzeConvert;
import com.xinqi.modules.exam.analyze.domain.CourseExamPaperAnalyzeEntity;
import com.xinqi.modules.exam.analyze.dto.GradeDistributionDTO;
import com.xinqi.modules.exam.analyze.dto.QuestionExplainDTO;
import com.xinqi.modules.exam.analyze.dto.QuestionExplainDTO.AnswerExplainData;
import com.xinqi.modules.exam.analyze.dto.QuestionScoreRateDTO;
import com.xinqi.modules.exam.analyze.dto.req.CourseExamAnalyzeStudentScoreQuestDTO;
import com.xinqi.modules.exam.analyze.dto.req.CourseExamPaperAnalyzeCreateDTO;
import com.xinqi.modules.exam.analyze.dto.req.CourseExamPaperAnalyzeDeleteDTO;
import com.xinqi.modules.exam.analyze.dto.req.CourseExamPaperAnalyzeQueryDTO;
import com.xinqi.modules.exam.analyze.dto.req.CourseExamPaperAnalyzeUpdateDTO;
import com.xinqi.modules.exam.analyze.dto.rsp.CourseExamAnalyzeStudentScoreDTO;
import com.xinqi.modules.exam.analyze.dto.rsp.CourseExamPaperAnalyzeResultDTO;
import com.xinqi.modules.exam.analyze.enmus.ScoreRangeEnum;
import com.xinqi.modules.exam.analyze.manager.CourseExamPaperAnalyzeManager;
import com.xinqi.modules.exam.analyze.service.CourseExamPaperAnalyzeService;
import com.xinqi.modules.exam.common.constants.ExamI18nConstants;
import com.xinqi.modules.exam.common.error.ExamErrors;
import com.xinqi.modules.exam.paper.domain.CourseExamPaperEntity;
import com.xinqi.modules.exam.paper.enums.ExamStatusEnum;
import com.xinqi.modules.exam.paper.manager.CourseExamPaperManager;
import com.xinqi.modules.exam.student.domain.CourseExamPaperStudentEntity;
import com.xinqi.modules.exam.student.dto.PaperAnswerDTO;
import com.xinqi.modules.exam.student.manager.CourseExamPaperStudentManager;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 课程测评分析服务层实现
 *
 * @author: linkai
 * @date: 2023/07/02
 */
@Validated
@Service("courseExamPaperAnalyzeService")
@RequiredArgsConstructor
public class CourseExamPaperAnalyzeServiceImpl implements CourseExamPaperAnalyzeService {
    private final CourseExamPaperAnalyzeConvert courseExamPaperAnalyzeConvert;
    private final CourseExamPaperAnalyzeManager courseExamPaperAnalyzeManager;
    private final CourseExamPaperStudentManager courseExamPaperStudentManager;
    private final CourseExamPaperManager courseExamPaperManager;

    /**
     * 分页查询 课程测评分析数据
     */
    @Override
    @DS("slaver")
    public PageInfo<CourseExamPaperAnalyzeResultDTO> page(Param pageable, CourseExamPaperAnalyzeQueryDTO query) {
        IPage<CourseExamPaperAnalyzeEntity> page = courseExamPaperAnalyzeManager.page(Pages.page(pageable), wrapper(query));
        return Pages.convert(page, courseExamPaperAnalyzeConvert::convert);
    }

    @Override
    @DS("slaver")
    public PageInfo<CourseExamAnalyzeStudentScoreDTO> findStudentScore(CourseExamAnalyzeStudentScoreQuestDTO questDTO) {
        IPage<CourseExamAnalyzeStudentScoreDTO> page = courseExamPaperAnalyzeManager.findStudentScore(Pages.page(questDTO), questDTO);
        return Pages.convert(page);
    }

    /**
     * 查询 课程测评分析数据
     */
    @Override
    public List<CourseExamPaperAnalyzeResultDTO> find(CourseExamPaperAnalyzeQueryDTO query) {
        return courseExamPaperAnalyzeManager.list(wrapper(query)).stream()
            .map(courseExamPaperAnalyzeConvert::convert).collect(Collectors.toList());
    }

    private LambdaQueryWrapper<CourseExamPaperAnalyzeEntity> wrapper(CourseExamPaperAnalyzeQueryDTO query) {
        LambdaQueryWrapper<CourseExamPaperAnalyzeEntity> wrapper = Queries.lambda();
        Queries.accept(query.getId(), v -> wrapper.eq(CourseExamPaperAnalyzeEntity::getId, v));
        Queries.accept(query.getExamId(), v -> wrapper.eq(CourseExamPaperAnalyzeEntity::getExamPaperId, v));
        return wrapper;
    }

    /**
     * 根据id查询 课程测评分析数据
     */
    @Override
    public CourseExamPaperAnalyzeResultDTO findById(Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        return Optional.ofNullable(courseExamPaperAnalyzeManager.findById(id)).map(courseExamPaperAnalyzeConvert::convert).orElse(null);
    }

    /**
     * 新增 课程测评分析数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long insert(@Valid CourseExamPaperAnalyzeCreateDTO dto) {
        CourseExamPaperAnalyzeEntity entity = courseExamPaperAnalyzeConvert.create(dto);
        courseExamPaperAnalyzeManager.save(entity);
        return entity.getId();
    }

    /**
     * 根据id修改 课程测评分析数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateById(@Valid CourseExamPaperAnalyzeUpdateDTO dto) {
        Optional.ofNullable(courseExamPaperAnalyzeManager.getById(dto.getId()))
            .orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("数据不存在"));
        CourseExamPaperAnalyzeEntity entity = courseExamPaperAnalyzeConvert.update(dto);
        return courseExamPaperAnalyzeManager.updateById(entity);
    }

    /**
     * 根据id删除 课程测评分析数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        return courseExamPaperAnalyzeManager.removeById(id);
    }

    /**
     * 根据id删除 课程测评分析数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(CourseExamPaperAnalyzeDeleteDTO dto) {
        return deleteById(dto.getId());
    }

    /**
     * 根据测试id查询
     */
    @Override
    public CourseExamPaperAnalyzeResultDTO findByExamId(Long examId) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(examId), "测评ID不能为空");
        return Optional.ofNullable(courseExamPaperAnalyzeManager.findByExamId(examId)).map(courseExamPaperAnalyzeConvert::convert)
            .orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("测评分析数据未生成"));
    }

    /**
     * 生成 课程测评分析数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean generate(Long examId) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(examId), "测评ID不能为空");
        CourseExamPaperEntity examPaper = Optional.ofNullable(courseExamPaperManager.findById(examId))
            .orElseThrow(() -> ExamErrors.EXAM_NOT_EXIST.asException(ExamI18nConstants.测评不存在));

        CommonErrors.BAD_REQUEST.check(Objects.equals(examPaper.getStatus(), ExamStatusEnum.已结束), "测评必须结束");
        CommonErrors.BAD_REQUEST.check(courseExamPaperStudentManager.isAllMark(examId), "测评必须全部批阅");
        // 获取学生试卷
        List<CourseExamPaperStudentEntity> studentList = courseExamPaperStudentManager.findByExamId(examId);
        if (studentList.isEmpty()) {
            throw CommonErrors.BAD_REQUEST.asException("测评没有学生参与");
        }
        // 获取测试信息
        CourseExamPaperAnalyzeEntity analyzeEntity = Optional.ofNullable(courseExamPaperAnalyzeManager.findByExamId(examId))
            .orElseGet(() -> {
                CourseExamPaperAnalyzeEntity temp = new CourseExamPaperAnalyzeEntity();
                temp.setExamPaperId(examId);
                return temp;
            });
        // 题目列表
        List<QuestionBaseDTO> questionList = examPaper.getQuestionContent();
        Map<Long, QuestionBaseDTO> questionMap = questionList.stream().collect(Collectors.toMap(QuestionBaseDTO::getId, Function.identity()));
        // 题目总数
        int questionTotal = examPaper.getQuestionTotal();
        // 题目总分
        BigDecimal totalScore = examPaper.getTotalScore();
        // 总人数
        int studentTotalNum = studentList.size();
        // 参与考试人数
        int examUserCount = 0;
        // 成绩分布
        List<GradeDistributionDTO> gradeDistributionList = ScoreRangeEnum.initGradeDistribution();
        // 试题得分率
        List<QuestionScoreRateDTO> questionScoreRateList = questionList.stream().map(v -> {
            QuestionScoreRateDTO e = new QuestionScoreRateDTO();
            e.setQuestionId(v.getId());
            e.setSort(v.getSort());
            e.setQuestionName(v.getQuestion());
            e.setQuestionType(v.getType());
            e.setTotalScore(v.getScore());
            e.setTotalNum(studentTotalNum);
            e.setRightNum(0);
            e.setRightScore(BigDecimal.ZERO);
            return e;
        }).collect(Collectors.toList());
        // 试题分析数据
        QuestionExplainData questionExplainData = QuestionExplainData.init(courseExamPaperAnalyzeConvert,
            questionList, studentTotalNum);
        QuestionScoreStatData questionScoreStatData = QuestionScoreStatData.init(questionTotal, totalScore, studentTotalNum);
        for (CourseExamPaperStudentEntity student : studentList) {
            // 学生 是否 参加考试
            if (Objects.equals(student.getIsExam(), YesNoEnum.YES.ordinal())) {
                examUserCount++;
            }
            // 只计算已批阅的学生试卷，没有批阅没有分数
            if (Objects.equals(student.getIsMarked(), YesNoEnum.YES.ordinal())) {
                // 学生分数处理
                questionScoreStatData.processStudentScore(student.getScore());
                // 添加学生成绩分布
                addGradeDistribution(gradeDistributionList, student.getScore(), totalScore);
                // 计算试题得分人数，计算试题得分率
                computeQuestionScoreRate(questionScoreStatData, questionScoreRateList, student, studentTotalNum, totalScore);
            }
            // 处理 学生答题情况
            questionExplainData.processStudent(student);
        }
        // 计算试题得分率
        // 计算得分率
        questionScoreRateList.forEach(QuestionScoreRateDTO::computeScoreRate);
        // 设置 解析中试题的得分率
        questionExplainData.computeScoreRate(questionScoreRateList);
        // 计算平均分，学生总分数 / 总人
        BigDecimal avgScore = BigDecimals.divide(questionScoreStatData.getSumScore(), new BigDecimal(studentTotalNum), 1, RoundingMode.HALF_UP);

        // 设置分析
        analyzeEntity.setQuestionTotal(questionTotal);
        analyzeEntity.setTotalScore(totalScore);
        analyzeEntity.setAllUserCount(studentTotalNum);
        analyzeEntity.setAvgScore(avgScore);
        analyzeEntity.setExamUserCount(examUserCount);
        analyzeEntity.setRightRate(questionScoreStatData.rightRate());
        analyzeEntity.setLowestScore(questionScoreStatData.getLowestScore());
        analyzeEntity.setHighestScore(questionScoreStatData.getHighestScore());
        analyzeEntity.setStudentGradeDistribution(gradeDistributionList);
        analyzeEntity.setQuestionScoreRateList(questionScoreRateList);
        analyzeEntity.setQuestionExplainList(questionExplainData.getQuestionList());
        // 保存或者更新
        courseExamPaperAnalyzeManager.saveOrUpdate(analyzeEntity);
        // 更新测评是否生成分析
        CourseExamPaperEntity temp = new CourseExamPaperEntity();
        temp.setId(examId);
        temp.setIsGenerateAssistant(YesNoEnum.YES.ordinal());
        courseExamPaperManager.updateById(temp);
        return true;
    }

    private void computeQuestionScoreRate(QuestionScoreStatData questionScoreStatData,
                                          List<QuestionScoreRateDTO> list, CourseExamPaperStudentEntity student,
                                          int studentTotalNum, BigDecimal totalScore) {
        List<PaperAnswerDTO> paperAnswerList = student.getPaperAnswer();
        for (PaperAnswerDTO paperAnswer : paperAnswerList) {
            addQuestionScoreRate(questionScoreStatData, list, paperAnswer, studentTotalNum, totalScore);
        }
    }

    private void addQuestionScoreRate(QuestionScoreStatData questionScoreStatData, List<QuestionScoreRateDTO> list, PaperAnswerDTO paperAnswer,
                                      int studentNum, BigDecimal totalScore) {
        if (list == null || paperAnswer == null) {
            return;
        }
        // 获取数据
        QuestionScoreRateDTO questionScoreRate = list.stream()
            .filter(v -> Objects.equals(v.getQuestionId(), paperAnswer.getQuestionId()))
            .findFirst().orElseGet(() -> {
                QuestionScoreRateDTO e = new QuestionScoreRateDTO();
                e.setQuestionId(paperAnswer.getQuestionId());
                e.setSort(paperAnswer.getSort());
                e.setQuestionName(paperAnswer.getQuestionName());
                e.setQuestionType(paperAnswer.getQuestionType());
                e.setTotalScore(paperAnswer.getScore());
                e.setTotalNum(studentNum);
                e.setRightNum(0);
                e.setRightScore(BigDecimal.ZERO);
                list.add(e);
                return e;
            });
        // 答对人数累加
        if (Objects.equals(paperAnswer.getIsRight(), Boolean.TRUE)) {
            questionScoreStatData.addRightNum(1);
            questionScoreRate.setRightNum(questionScoreRate.getRightNum() + 1);
        }
        // 试题分数累加
        questionScoreStatData.addRightScore(paperAnswer.getStudentScore());
        questionScoreRate.setRightScore(BigDecimals.add(questionScoreRate.getRightScore(), paperAnswer.getStudentScore()));
    }

    /**
     * 添加学生成绩分布
     */
    public void addGradeDistribution(List<GradeDistributionDTO> list, BigDecimal score, BigDecimal totalScore) {
        if (list == null || score == null || totalScore == null) {
            return;
        }
        ScoreRangeEnum scoreRange = ScoreRangeEnum.scoreRange(score, totalScore);
        addGradeDistribution(list, scoreRange);
    }

    /**
     * 添加学生成绩分布
     */
    public void addGradeDistribution(List<GradeDistributionDTO> list, ScoreRangeEnum scoreRange) {
        if (list == null) {
            return;
        }
        GradeDistributionDTO gradeDistribution = list.stream().filter(v -> Objects.equals(v.getScoreRange(), scoreRange))
            .findFirst().orElseGet(() -> {
                GradeDistributionDTO e = new GradeDistributionDTO();
                e.setScoreRange(scoreRange);
                e.setStudentNum(0);
                list.add(e);
                return e;
            });
        gradeDistribution.setStudentNum(gradeDistribution.getStudentNum() + 1);
    }


    @Data
    public static class QuestionExplainData {
        private List<QuestionExplainDTO> questionList;
        private Map<Long, QuestionExplainDTO> questionMap;

        public static QuestionExplainData init(CourseExamPaperAnalyzeConvert courseExamPaperAnalyzeConvert,
                                               List<QuestionBaseDTO> list,
                                               int studentTotalNum
        ) {
            QuestionExplainData data = new QuestionExplainData();
            // 初始化 试题解析列表
            List<QuestionExplainDTO> questionExplainlist = list.stream().map(question -> {
                QuestionExplainDTO questionExplain = courseExamPaperAnalyzeConvert.convert(question);
                questionExplain.setAllUserCount(studentTotalNum);
                questionExplain.setAnswerUserCount(0);
                questionExplain.setUnAnswerUserCount(0);
                questionExplain.setRightUserCount(0);
                questionExplain.setErrorUserCount(0);
                questionExplain.setQuestionScoreRate(BigDecimal.ZERO);
                questionExplain.setAnswerExplainList(getAnswerExlainList(question, studentTotalNum));
                return questionExplain;
            }).collect(Collectors.toList());
            // 设置 试题解析列表
            data.setQuestionList(questionExplainlist);
            data.setQuestionMap(questionExplainlist.stream().collect(Collectors.toMap(QuestionBaseDTO::getId, v -> v)));
            return data;
        }

        /**
         * 处理学生，答案
         */
        public void processStudent(CourseExamPaperStudentEntity student) {
            for (PaperAnswerDTO paperAnswer : student.getPaperAnswer()) {
                // 获取 答题解析
                QuestionExplainDTO questionExplain = questionMap.get(paperAnswer.getQuestionId());
                if (questionExplain == null) {
                    continue;
                }
                // 是否作答
                if (Objects.equals(paperAnswer.getIsReply(), Boolean.TRUE)) {
                    // 已作答
                    answered(student, paperAnswer, questionExplain);
                } else {
                    // 未作答
                    unAnswered(student, paperAnswer, questionExplain);
                }
            }
        }

        /**
         * 未作答
         */
        private void unAnswered(CourseExamPaperStudentEntity student, PaperAnswerDTO paperAnswer, QuestionExplainDTO questionExplain) {
            questionExplain.setUnAnswerUserCount(questionExplain.getUnAnswerUserCount() + 1);
            // 未作答，未选
            questionExplain.setErrorUserCount(questionExplain.getErrorUserCount() + 1);
            analyzeAnswer(student, QuestionTypeEnum.of(paperAnswer.getQuestionType()), paperAnswer, questionExplain);
        }

        /**
         * 已作答
         */
        private void answered(CourseExamPaperStudentEntity student, PaperAnswerDTO paperAnswer, QuestionExplainDTO questionExplain) {
            // 已作答
            questionExplain.setAnswerUserCount(questionExplain.getAnswerUserCount() + 1);
            // 获取题目类型
            QuestionTypeEnum questionType = QuestionTypeEnum.of(paperAnswer.getQuestionType());
            // 是否答对
            if (Objects.equals(paperAnswer.getIsRight(), Boolean.TRUE)) {
                // 答对
                questionExplain.setRightUserCount(questionExplain.getRightUserCount() + 1);
                analyzeAnswer(student, questionType, paperAnswer, questionExplain);
            } else {
                // 答错
                questionExplain.setErrorUserCount(questionExplain.getErrorUserCount() + 1);
                // 解析答案
                analyzeAnswer(student, questionType, paperAnswer, questionExplain);
            }
        }

        private void analyzeAnswer(CourseExamPaperStudentEntity student,
                                   QuestionTypeEnum questionType,
                                   PaperAnswerDTO paperAnswer,
                                   QuestionExplainDTO questionExplain) {
            // 学生答案
            List<String> studentAnswerList = QuestionUtils.answer2List(questionType, paperAnswer.getStudentAnswer());
            // 获取答案解列表
            List<AnswerExplainData> answerExplainList = questionExplain.getAnswerExplainList();
            // 分析那些答错
            for (int i = 0; i < answerExplainList.size(); i++) {
                answerPaper(
                    answerExplainList.get(i),
                    student.getStudentId(),
                    // 判断答对 还是 答错
                    isAnswerRight(answerExplainList, studentAnswerList, questionType, i)
                );
            }
        }

        /**
         * 答题解析
         */
        private void answerPaper(AnswerExplainData answerExplain, Long studentId, Selected selected) {
            // 学生答对，并且答案是正确
            switch (selected) {
                case 选对:
                    answerExplain.setRightUserCount(answerExplain.getRightUserCount() + 1);
                    answerExplain.getRightUserList().add(studentId);
                    break;
                case 选错:
                    answerExplain.setErrorUserCount(answerExplain.getErrorUserCount() + 1);
                    answerExplain.getErrorUserList().add(studentId);
                    break;
                case 未选:
                    // 暂时不处理
                    break;
            }
        }

        /**
         * 判断答案是否正确，1-答对，2-答错，3-未选择
         */
        private Selected isAnswerRight(List<AnswerExplainData> answerExplainList,
                                       List<String> studentAnswerList,
                                       QuestionTypeEnum questionType,
                                       int idx) {
            if (studentAnswerList == null) {
                studentAnswerList = Collections.emptyList();
            }
            // 答案解析
            AnswerExplainData answerExplainData = answerExplainList.get(idx);
            String answer = answerExplainData.getAnswer();
            Boolean isRight = answerExplainData.getIsRight();
            // 是否选择
            boolean isSelect;
            if (Objects.equals(questionType, QuestionTypeEnum.ANSWER_CLOZE)) {
                // 判断位置上的，答案是否一致
                try {
                    String studentAnswer = studentAnswerList.get(idx);
                    if (Objects.equals(answer, studentAnswer)) {
                        return Selected.选对;
                    } else {
                        return Selected.选错;
                    }
                } catch (Exception ignored) {
                    return Selected.选错;
                }
            } else {
                // 判断是否包含答案
                isSelect = studentAnswerList.contains(answer);
            }
            if (isSelect && isRight) {
                // 答对
                return Selected.选对;
            } else if (isSelect) {
                // 答错
                return Selected.选错;
            } else if (isRight) {
                // 未选择
                return Selected.选错;
            } else {
                // 未选择
                return Selected.未选;
            }
        }

        public void computeScoreRate(List<QuestionScoreRateDTO> questionScoreRateList) {
            Map<Long, QuestionScoreRateDTO> map = questionScoreRateList.stream()
                .collect(Collectors.toMap(QuestionScoreRateDTO::getQuestionId, v -> v));
            for (QuestionExplainDTO questionExplain : getQuestionList()) {
                // 设置得分率
                Optional.ofNullable(map.get(questionExplain.getId()))
                    .ifPresent(v -> questionExplain.setQuestionScoreRate(v.getQuestionScoreRate()));
            }

        }

        private static List<AnswerExplainData> getAnswerExlainList(QuestionBaseDTO question, int studentTotalNum) {
            QuestionTypeEnum type = QuestionTypeEnum.of(question.getType());
            ImmutableList.Builder<AnswerExplainData> list = ImmutableList.builder();
            switch (type) {
                case ANSWER_JUDGE:
                case ANSWER_RADIO:
                case ANSWER_MULTIPLE:
                case ANSWER_INDEFINITE:
                    list.addAll(initAnswerExplainDataList(question.getOptionList(), studentTotalNum));
                    break;
                case ANSWER_CLOZE:
                    list.addAll(initAnswerExplainDataList(QuestionUtils.answer2Array(type, question.getAnswer()), studentTotalNum));
                    break;
            }
            return list.build();
        }

        private static List<AnswerExplainData> initAnswerExplainDataList(String[] answerList, int studentTotalNum) {
            return Stream.of(answerList)
                .map(v -> initAnswerExplainData(v, true, studentTotalNum))
                .collect(Collectors.toList());
        }

        private static List<AnswerExplainData> initAnswerExplainDataList(List<QuestionOptionsDTO> optionList, int studentTotalNum) {
            return optionList.stream()
                .map(v -> initAnswerExplainData(v.getId(), Objects.equals(v.getSelected(), YesNoEnum.YES.ordinal()), studentTotalNum))
                .collect(Collectors.toList());
        }

        private static AnswerExplainData initAnswerExplainData(String answer, Boolean isRight, int studentTotalNum) {
            AnswerExplainData data = new AnswerExplainData();
            data.setAnswer(answer);
            data.setIsRight(isRight);
            data.setRightUserCount(0);
            data.setErrorUserCount(0);
//            data.setUnselectedUserCount(0);
            data.setRightUserList(new ArrayList<>(studentTotalNum));
            data.setErrorUserList(new ArrayList<>(studentTotalNum));
//            data.setUnselectedUserList(new ArrayList<>(studentTotalNum));
            return data;
        }

    }

    @Data
    public static class QuestionScoreStatData {
        /**
         * 总题目数
         */
        private Integer totalNum;
        /**
         * 答对题目数
         */
        private Integer rightNum = 0;
        /**
         * 所有题目分数
         */
        private BigDecimal totalScore;
        /**
         * 所有答对题目分数
         */
        private BigDecimal rightScore = BigDecimal.ZERO;
        /**
         * 学生总分
         */
        private BigDecimal sumScore = BigDecimal.ZERO;
        /**
         * 最低分
         */
        private BigDecimal lowestScore = BigDecimal.ZERO;
        /**
         * 最高分
         */
        private BigDecimal highestScore = BigDecimal.ZERO;

        public static QuestionScoreStatData init(int questionTotal, BigDecimal totalScore, int studentTotalNum) {
            QuestionScoreStatData data = new QuestionScoreStatData();
            data.setTotalNum(questionTotal * studentTotalNum);
            data.setTotalScore(BigDecimals.multiply(totalScore, studentTotalNum));
            data.setLowestScore(totalScore);
            return data;
        }

        /**
         * 处理学生分数
         */
        public void processStudentScore(BigDecimal score) {
            if (sumScore == null) {
                sumScore = score;
            } else {
                sumScore = BigDecimals.add(sumScore, score);
            }
            // 计算最低分
            if (lowestScore.compareTo(score) > 0) {
                lowestScore = score;
            }
            // 计算最高分
            if (highestScore.compareTo(score) < 0) {
                highestScore = score;
            }
        }

        public void addRightNum(int i) {
            if (rightNum == null) {
                rightNum = 0;
            } else {
                rightNum += i;
            }
        }

        public void addRightScore(BigDecimal i) {
            if (rightScore == null) {
                rightScore = i;
            } else {
                rightScore = BigDecimals.add(rightScore, i);
            }
        }

        /**
         * 答题平均得分率，所有答对题的分数 / 总人数 * 题目分数
         */
        public BigDecimal rightRate() {
            if (totalScore == null || rightScore == null
                || rightScore.compareTo(BigDecimal.ZERO) == 0
                || totalScore.compareTo(BigDecimal.ZERO) == 0
            ) {
                return BigDecimal.ZERO;
            }
            return BigDecimals.divide(rightScore, totalScore);
        }
    }

    public enum Selected {
        选对, 选错, 未选
    }

}
